// ===============================================
// dio_interceptor
//
// Create by Will on 2020/10/5 4:13 PM
// Copyright @flutter_core_kit.All rights reserved.
// ===============================================

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';

import '../core/core_kit.dart';
import '../core/exception/api_exception.dart';
import 'entity/response/base_response.dart';

class CoreKitInterceptor extends Interceptor {
  static int? _lastTimestamp;

  static int? get lastTimestamp => _lastTimestamp;

  static set lastTimestamp(int? value) {
    final oldValue = lastTimestamp;
    if (oldValue == null || oldValue < value!) {
      _lastTimestamp = value;
    }
  }

  /// 在此处改造请求，统一加入Token
  @override
  Future<dynamic> onRequest(
    RequestOptions options,
    RequestInterceptorHandler handler,
  ) async {
    final headers = options.headers;
    final apiHeaders = await CoreKit.config?.apiHeadersGenerator;
    if (apiHeaders != null) {
      for (final apiHeader in apiHeaders.entries) {
        headers.putIfAbsent(apiHeader.key, () => apiHeader.value);
      }
    }
    options.headers = headers;

    return super.onRequest(options, handler);
  }

  @override
  Future<dynamic> onResponse(
    Response<dynamic> response,
    ResponseInterceptorHandler handler,
  ) async {
    final entity = BaseResponse.tryParse(response.data);

    if (entity != null) {
      lastTimestamp = entity.timestamp;

      if (entity.isSuccess) {
        // 抛掉BaseResponse的包装，直接返回result
        response.data = entity.data;
        // return handler.next(response);
        return super.onResponse(response, handler);
      }

      if (kDebugMode) {
        debugPrint('*** Response ***');
        _printResponse(response);
      }

      // 触发异常
      return handler.reject(
        DioException(
          requestOptions: response.requestOptions,
          response: response,
          type: DioExceptionType.badResponse,
          error: CoreKitAPIException(
            entity.code,
            message: entity.msg,
          ),
        ),
      );
    }

    return super.onResponse(response, handler);
  }

  @override
  Future<dynamic> onError(
    DioException err,
    ErrorInterceptorHandler handler,
  ) async {
    final entity = BaseResponse.tryParse(err.response?.data);

    if (entity != null) {
      lastTimestamp = entity.timestamp;

      // 触发异常
      return handler.reject(
        DioException(
          requestOptions: err.requestOptions,
          response: err.response,
          type: DioExceptionType.badResponse,
          error: CoreKitAPIException(
            entity.code,
            message: entity.msg,
          ),
        ),
      );
    }

    return super.onError(err, handler);
  }

  void _printResponse(Response<dynamic> response) {
    _printKV('uri', response.requestOptions.uri);
    _printKV('statusCode', response.statusCode);
    if (response.isRedirect) {
      _printKV('redirect', response.realUri);
    }
    debugPrint('headers:');
    response.headers.forEach((key, v) => _printKV(' $key', v.join('\r\n\t')));
    debugPrint('Request Data:');
    _printAll(response.requestOptions.data);
    debugPrint('Response Text:');
    _printAll(response.toString());
    debugPrint('');
  }

  void _printKV(String key, Object? v) {
    debugPrint('$key: $v');
  }

  void _printAll(dynamic msg) {
    msg.toString().split('\n').forEach(debugPrint);
  }
}

extension RequestOptionsExt on RequestOptions {
  Future<bool> isFromBaseUrl() async {
    final baseUrls = await CoreKit.config?.apiBaseUrlsGetter;
    bool test(String baseUrl) => uri.toString().startsWith(baseUrl);
    return baseUrls?.any(test) == true;
  }
}
